Split a vector or a list into groups, given a predicate function.

group_if(x, predicate, na.rm = FALSE)

group_eq(x, na.rm = FALSE)

Arguments

x

a vector or a list to split into groups.

predicate

a binary function returning a boolean value.

na.rm

if x is atomic, delete missing values before grouping.

Value

A list where each element is a group (flattening this list should give back the same values in the same order). Element names are kept.

Details

predicate will be applied to 2 adjacent elements. If it evaluates to TRUE, those elements belong to the same group, otherwise they belong to different groups.

Grouping on equality is the most natural approach, therefore group_eq is a convenient shortcut defined as

  • group_if(x, predicate = `==`) for an atomic vector;

  • group_if(x, predicate = identical) for a list.

group_if (resp. group_eq) is inspired by groupBy (resp. group) in Haskell. Note that group_if behaves a little differently : while in Haskell, the comparison is made with the first element in the group, in this R-version the comparison is made with the adjacent element.

The operator %on% may be helpful to create a predicate with readable syntax.

Examples

x1 <- c(3, 4, 2, 2, 1, 1, 1, 3) group_eq(x1)
#> [[1]] #> [1] 3 #> #> [[2]] #> [1] 4 #> #> [[3]] #> [1] 2 2 #> #> [[4]] #> [1] 1 1 1 #> #> [[5]] #> [1] 3 #>
group_if(x1, `<=`)
#> [[1]] #> [1] 3 4 #> #> [[2]] #> [1] 2 2 #> #> [[3]] #> [1] 1 1 1 3 #>
group_if(x1, function(x, y) abs(x - y) > 1)
#> [[1]] #> [1] 3 #> #> [[2]] #> [1] 4 2 #> #> [[3]] #> [1] 2 #> #> [[4]] #> [1] 1 #> #> [[5]] #> [1] 1 #> #> [[6]] #> [1] 1 3 #>
x2 <- c(3, 4, 2, -2, -1, 1, 1, 3) group_if(x2, `==` %on% abs)
#> [[1]] #> [1] 3 #> #> [[2]] #> [1] 4 #> #> [[3]] #> [1] 2 -2 #> #> [[4]] #> [1] -1 1 1 #> #> [[5]] #> [1] 3 #>
x3 <- list(1:3, 1:3, 3:5, 1, 2) group_if(x3, `==` %on% length)
#> [[1]] #> [[1]][[1]] #> [1] 1 2 3 #> #> [[1]][[2]] #> [1] 1 2 3 #> #> [[1]][[3]] #> [1] 3 4 5 #> #> #> [[2]] #> [[2]][[1]] #> [1] 1 #> #> [[2]][[2]] #> [1] 2 #> #>